"""过期前自动移库功能"""

import logging
from datetime import timedelta

from odoo import models, api, fields
from odoo.tools import float_compare
from odoo.exceptions import UserError, ValidationError
from odoo.tools import groupby


_logger = logging.getLogger(__name__)


class ManualMove(models.TransientModel):
    _name = 'nd.move.expire.wizard'
    _description = '移动过期产品向导'

    def _get_dest_location(self):
        Lot = self.env['stock.production.lot']
        _, move_location_id = Lot._get_setting_info()
        return move_location_id

    location_dest_id = fields.Many2one('stock.location', string="移动至", default=_get_dest_location)
    quant_ids = fields.Many2many('stock.quant', string="即将过期批次")
    expire_date = fields.Datetime('过期时间', default=lambda x: fields.Datetime.now())

    @api.onchange('location_dest_id', 'expire_date')
    def onchange_quant_ids(self):
        """获取即将过期的quant"""
        location_ids = self.env['stock.location'].search([('usage', '=', 'internal')])
        need_move_location = location_ids - self.location_dest_id
        expire_quants = self.env['stock.quant'].search([('removal_date', '<=', self.expire_date),
                                                        ('quantity', '>', 0),
                                                        ('location_id', 'in', need_move_location.ids),
                                                        ('lot_id', '!=', False)])
        # self.quant_ids = expire_quants
        self.update({'quant_ids': expire_quants})
        return {'domain': {'quant_ids': [('id', 'in', expire_quants.ids)]}}

    @api.multi
    def confirm(self):
        """确认移动选中的quant至选定的位置"""
        if self.location_dest_id and self.quant_ids:
            illegal_quants = self.quant_ids.filtered(lambda x: x.location_id.usage != 'internal' or x.quantity <= 0)
            if illegal_quants:
                raise UserError(f'不能选择库位不正确或者数量小于等于0的批次:"{illegal_quants[0].lot_id.name}"')
            picking_id = self.env['stock.production.lot']._nd_generate_moves(self.quant_ids, self.location_dest_id.id)
            if picking_id:
                picking_id.action_confirm()
                _logger.info(f'针对{self.quant_ids}生成了到{self.location_dest_id}的内部移动单{picking_id}')
                return {
                    'name': "移动即将过期的产品",
                    'type': 'ir.actions.act_window',
                    'view_type': 'form',
                    'view_mode': 'form',
                    'res_model': 'stock.picking',
                    'view_id': self.env.ref('stock.view_picking_form').id,
                    'res_id': picking_id.id
                }


class ProductionLot(models.Model):
    _inherit = 'stock.production.lot'

    @api.model
    def auto_move_expiry_products(self):
        """自动移动即将过期的批次"""
        auto_move, move_location_id = self._get_setting_info()
        today = fields.Datetime.now()
        if auto_move and move_location_id:
            location_ids = self.env['stock.location'].search([('usage', '=', 'internal'), ('id', '!=', move_location_id)])
            expire_quants = self.env['stock.quant'].search([('removal_date', '<=', today),
                                                            ('quantity', '>', 0),
                                                            ('location_id', 'in', location_ids.ids),
                                                            ('lot_id', '!=', False)])
            picking_id = self._nd_generate_moves(expire_quants, move_location_id)
            if picking_id:
                _logger.info(f'针对{expire_quants}生成了到 ID为{move_location_id}的库位的的内部调拨{picking_id}')
                picking_id.button_validate()
                _logger.info(f'验证了内部调拨{picking_id}')

    def _get_setting_info(self):
        """获取过期移动的相关配置信息"""
        Parameter = self.env['ir.config_parameter'].sudo()
        auto_move = Parameter.get_param('nd.expire_auto_move', default=False)
        move_location_id = Parameter.get_param('nd.nd_expire_move_location_id', default=False)
        move_location_id = move_location_id and int(move_location_id) or False
        return bool(auto_move), move_location_id

    def _nd_generate_moves(self, quants, location_id):
        """
        生成到location_id的库存移动
        :param quants: stock.quant,待移动的quant
        :param location_id: int,移动目标位置ID
        :return: stock.picking,生成的内部调拨单
        """
        if quants and location_id:
            grouped_quants = groupby(quants, lambda x: x.product_id.id)
            # 默认原位置,没有逻辑影响,但是必须存在.
            default_src_location_id = self.env['stock.location'].search([('usage', '=', 'internal')], limit=1)

            moves = []
            for product_id, _ in grouped_quants:
                product = self.env['product.product'].browse(product_id)
                moves.append((0, 0, {
                            'product_id': product_id,
                            'location_id': location_id,
                            'location_dest_id': default_src_location_id.id,
                            'name': product.display_name,
                            'product_uom': product.uom_id.id}))

            data = {
                'location_id': location_id,
                'location_dest_id': default_src_location_id.id,
                'picking_type_id': self.env.ref('stock.picking_type_internal').id,
                'note': '过期移库',
                'move_lines': moves,
            }

            picking_id = self.env['stock.picking'].create(data)
            move_info = {move.product_id.id: move for move in picking_id.move_lines}
            move_lines = []
            for product_id, quants in grouped_quants:
                move_id = move_info[product_id]
                for quant in quants:
                    # 需要针对每个批次的每个位置 来创建一个move_lines,方便选位置和批次
                    move_line_data = move_id._prepare_move_line_vals()
                    move_line_data['lot_id'] = quant.lot_id.id
                    move_line_data['location_id'] = quant.location_id.id
                    move_line_data['location_dest_id'] = location_id
                    move_line_data['qty_done'] = quant.quantity
                    move_line_data['product_uom_id'] = quant.product_uom_id.id
                    move_lines.append(move_line_data)
            self.env['stock.move.line'].create(move_lines)
            return picking_id
        else:
            return self.env['stock.picking']






